
#include "linux_def.h"
#include "core.h"

//static void *palloc_block(pool_t *pool, size_t size);
//static void *palloc_large(pool_t *pool, size_t size);

void *pcalloc(pool_t *pool, size_t size)
{
	void	*p;

	p = palloc(pool, size);
	if (p)
		bzero(p, size);

	return p;
}

void	*palloc(pool_t *pool, size_t size)
{
	char *m;
	pool_t	*p, *n, *current;
	pool_large_t	*large;

	if (size <= MAX_ALLOC_FROM_POOL &&
		size <= (size_t)(pool->end - (char*)pool) - (size_t)align_ptr (sizeof(pool_t), sizeof(unsigned long))
	){	
		p = pool->current;
		current = p;		
			
		for (;;){
			if (size < sizeof(int) || (size & 1))
				m = p->last;
			else
				m = align_ptr(p->last, sizeof(unsigned long));

			if ((size_t)(p->end-m) >= size){
				p->last = m + size;
				return m;
			}

			if ((size_t)(p->end-m) < sizeof(unsigned long))
				current = p->next;
			if (p->next == NULL)
				break;

			p = p->next;
			pool->current = current;
		}
		
		n = create_pool((size_t)(p->end - (char *)p), p->log);
		if (n == NULL)
			return NULL;

		pool->current = current ? current : n;
		p->next = n;
		m = align_ptr(n->last, sizeof(unsigned long));
		n->last = m + size;

		return m;
	}

	if ((p = malloc(size)) == NULL)
		return NULL;

	large = palloc(pool, sizeof(pool_large_t));
	if (large == NULL){
		free(p);
		return NULL;
	}

	large->alloc = p;
	large->next = pool->large;
	pool->large = large;

	return p;
}
/*
static void *palloc_block(pool_t *pool, size_t size)
{
	char	*m;
	size_t	psize;
	pool_t	*p, *new, *current;

	psize = (size_t)(pool->d.end - (char*)pool);	//计算pool的大小

	m = memalign(&m, POOL_ALIGNMENT, psize);	//分配一块和pool一样大小的内存块
	if (m == NULL)
		return NULL;
	
	new = (pool_t*)m;

	new->end	= m + psize;	//新内存块的末端
	new->next	= NULL;
	new->failed	= 0;

//	m	+= sizoef(pool_data_t);	//m指向最后一个数据块的起始位置
//	m	= align_ptr(m, _MAX_ALIGNMENT); //按4字节对齐

	new->last	= m + size;	//在数据块分配size大小内存并设置last指针
	current	= pool->current;

	for (p=current; p->d.next; p=p->d.next){
		if (p->d.failed++ > 4)
			current = p->d.next;
	}

	p->d.next = new;
	pool->current = current ? current : new;

	return m;
}
*/

/*
static void *palloc_large(pool_t *pool, size_t size)
{
	void	*p;
	int	n;
	pool_large_t	*large;

	p = malloc(size);
	if (p == NULL)
		return NULL;

	n = 0;
	for (large=pool->large; large; large=large->next){
		if (large->alloc == NULL){
			large->alloc = p;
			return p;
		}
		if (n++ > 3)
			break;
	}

	large = palloc(pool, sizeof(pool_large_t));
	if (large == NULL){
		free(p);
		return NULL;
	}

	large->alloc	= p;
	large->next	= pool->large;
	pool->large	= large;

	return p;
}
*/

pool_t *create_pool(size_t size, log_t *log)
{
	pool_t	*p;

	p = (pool_t*)malloc(size);
	if (p == NULL){
		fprintf(stderr, "memalign() failed.\n");
		return NULL;
	}

	p->last	= (char*)p + sizeof(pool_t);	//指向当前内存块的末端
	p->end	= (char*)p + size;	//指向内存池结束的地方
	p->current	= p;	//当前内存块指向
	p->next	= NULL;	
	p->large	= NULL;
	p->cleanup	= NULL;

	//p->log		= log;
	//p->chain	= NULL;

	return p;
}

void destroy_pool(pool_t *pool)
{
	pool_t	*p, *n;
	pool_large_t	*l;
	pool_cleanup_t	*c;

	for (c=pool->cleanup; c; c=c->next){	//清楚内存块中数据
		if (c->handler)
			c->handler(c->data);
	}

	for (l=pool->large; l; l=l->next){	//清楚申请的大块内存
		if (l->alloc)
			free(l->alloc);
	}

	for (p=pool, n=pool->next; ;p=n, n=n->next){	//清楚内存池
		free(p);
		if (n == NULL)
			break;
	}
}

int pfree(pool_t *pool, void *p)
{
	pool_large_t	*l;
	
	for (l=pool->large; l; l=l->next){
		if (p == l->alloc){
			free(l->alloc);
			l->alloc = NULL;
			return 0;
		}
	}

	return -1;
}

pool_cleanup_t *pool_cleanup_add(pool_t *p, size_t size)
{
	pool_cleanup_t  *c;

	c = palloc(p, sizeof(pool_cleanup_t));
	if (c == NULL) {
		return NULL;
	}

	if (size) {
		c->data = palloc(p, size);
		if (c->data == NULL) {
			return NULL;
		}
	}else{
		c->data = NULL;
	}

	c->handler = NULL;
	c->next = p->cleanup;

	p->cleanup = c;

	return c;
}

void pool_cleanup_file(void *data)
{
	pool_cleanup_file_t	*c = data;

	close(c->fd);
}

void pool_delete_file(void *data)
{
	pool_cleanup_file_t	*c = data;

	close(c->fd);
}
